package cn.web.web_module.service.impl;

import cn.itcast.pojo.horseman;
import cn.itcast.service.orderService;
import cn.message.service.IHorsemanService;
import cn.web.web_module.service.AutomaticSendService;
import com.alibaba.fastjson.JSON;
import org.apache.commons.collections.IteratorUtils;
import org.apache.commons.lang.StringUtils;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author: 张松
 * @Description:  自动派单
 * @Date: Created in 10:42 2020/6/30
 * @Modified By:
 */
@Service
public class AutomaticSendImpl implements AutomaticSendService {

    @Resource
    private IHorsemanService horsemanService;

    @Resource
    private orderService orderService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    /**
     *
     * @Description: 获取全部骑手的经纬度
     *
     * @auther: 张松
     * @date: 8:53 2020/7/1
     * @param: [latAndLon]
     * @return: java.util.Map<java.lang.String,java.lang.Object>    返回离用户最近的骑手
     *
     */
    public Map<String, Object> getApproachingHorseman(Map<String,Double> latAndLon){
        String allHorsemanLatAndLon = stringRedisTemplate.opsForValue().get("AllHorsemanLatAndLon");
        if (StringUtils.isBlank(allHorsemanLatAndLon)){
            List<horseman> horsemen = horsemanService.selectAllHorsemanLatAndLon();
            Iterator<horseman> iterator = horsemen.iterator();
            while (iterator.hasNext()){
                if(Integer.parseInt(iterator.next().getHorsemanType())==2){
                    iterator.remove();
                }
            }
            stringRedisTemplate.opsForValue().set("AllHorsemanLatAndLon", JSON.toJSON(horsemen).toString(),10, TimeUnit.SECONDS);
            allHorsemanLatAndLon = stringRedisTemplate.opsForValue().get("AllHorsemanLatAndLon");
        }
        List<horseman> horsemen = JSON.parseArray(allHorsemanLatAndLon, horseman.class);
        Map<String, Double> NearestDistance = seekNearestDistance(horsemen, latAndLon);  //传入骑手集合和用户位置,获取key为骑手的openid和value为离用户距离的map
        Map<String, Object> horsemenAndDistance = nearestHorsemen(NearestDistance);
        return horsemenAndDistance;
    }


    /**
     *
     * @Description: 计算离用户最近的骑手
     *
     * @auther: 张松
     * @date: 13:57 2020/7/1
     * @param: [NearestDistance]
     * @return: java.util.Map<java.lang.String,java.lang.Object>返回一个离用户最近的骑手和骑手离用户的距离
     *
     */
    public Map<String,Object> nearestHorsemen(Map<String, Double> NearestDistance){
        List<String> keyHorsemenOpenId = new ArrayList<>();
        List<Double> valueHorsemenUserDistance = new ArrayList<>();
        String minDistanceHorsemenOpenId;
        Double minHorsemenUserDistance;
        for (String strings:NearestDistance.keySet()){
            keyHorsemenOpenId.add(strings);
            valueHorsemenUserDistance.add(NearestDistance.get(strings));
        }
        minHorsemenUserDistance=valueHorsemenUserDistance.get(0);
        minDistanceHorsemenOpenId=keyHorsemenOpenId.get(0);
        for (int i=0;i<valueHorsemenUserDistance.size();i++){
            if (minHorsemenUserDistance>valueHorsemenUserDistance.get(i)){
                minHorsemenUserDistance=valueHorsemenUserDistance.get(i);
                minDistanceHorsemenOpenId=keyHorsemenOpenId.get(i);
            }
        }
        List<horseman> horsemen = horsemanService.selectHorsemanOpenId(minDistanceHorsemenOpenId);
        Map<String,Object> horsemenAndDistance= new HashMap<>();
        horsemenAndDistance.put("minDistanceHorsemen",horsemen);
        horsemenAndDistance.put("minHorsemenUserDistance",minHorsemenUserDistance);
        return horsemenAndDistance;
    }



    /**
     *
     * @Description:  骑手经纬度与用户经纬度比较
     *
     * @auther: 张松
     * @date: 8:50 2020/7/1
     * @param: [horsemen, latAndLon]
     * @return: java.util.Map<java.lang.String,java.lang.Object> 返回一个map,key为骑手的openid,value为骑手离用户的距离
     *
     */
    public Map<String,Double> seekNearestDistance(List<horseman> horsemen,Map<String,Double> latAndLon){
        Map<String,Double> NearestDistance = new HashMap<>();
        horsemen.forEach((v)->{
            GlobalCoordinates source = new GlobalCoordinates(Double.parseDouble(v.getHorsemanLat()), Double.parseDouble(v.getHorsemanLon()));
            GlobalCoordinates target = new GlobalCoordinates(latAndLon.get("userLat"),latAndLon.get("userLon"));
            Double distanceMeter = getDistanceMeter(source, target, Ellipsoid.Sphere);
            NearestDistance.put(v.getOpenId(),distanceMeter);
        });
        return NearestDistance;
    }

    /**
     *
     * @Description:    获取与用户最近的骑手
     *
     * @auther: 张松
     * @date: 8:49 2020/7/1
     * @param: [latAndLon]
     * @return: java.util.Map<java.lang.String,java.lang.Object>    返回离用户最近的骑手
     *
     */
    public Map<String,Object> getHorsemanAndUserDistance(Map<String,Double> latAndLon){

        Map<String,Object> dinates= new HashMap<>();
        getApproachingHorseman(latAndLon);
        GlobalCoordinates source = new GlobalCoordinates(latAndLon.get("horsemanLat"), latAndLon.get("horsemanLon"));
        GlobalCoordinates target = new GlobalCoordinates(latAndLon.get("userLat"), latAndLon.get("userLon"));
        double meter = getDistanceMeter(source, target, Ellipsoid.Sphere);
        dinates.put("Sphere",meter);
        System.out.println("Sphere坐标系计算结果："+meter + "米");
        return dinates;
    }


    /**
     *
     * @Description: 计算两个经纬度之间的距离
     *
     * @auther: 张松
     * @date: 8:48 2020/7/1
     * @param: [gpsFrom, gpsTo, ellipsoid]
     * @return: java.lang.Double        返回一个Double类型的距离长度
     *
     */
    Double getDistanceMeter (GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid){
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid,gpsFrom,gpsTo);
        return geoCurve.getEllipsoidalDistance();
    }

}
